import numpy as np
import matplotlib.pyplot as plt
import torch
mu, sigma = 0, 0.5 # mean and standard deviation
noise = np.random.normal(mu, sigma, 10)
X = np.random.rand(10)*5
Y = 2*X + 1 + noise
plt.axis([0, 5, 0, 12])
plt.plot(X,Y,'bo')
plt.show()
device = 'cuda' if torch.cuda.is_available() else 'cpu'
X = torch.from_numpy(X).float().to(device)
Y = torch.from_numpy(Y).float().to(device)
m = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
b = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
Hay que distinguir entre los tensores creados para almacenar datos y los tensores creados para almacenar variables (pesos o parámetros). Para los primeros no necesitaremos calcular sus gradientes, para los segundos, sí.
optimizer = torch.optim.SGD([m, b], lr=0.001)
# Defines a MSE loss function
loss_fn = torch.nn.MSELoss(reduction='sum')
for _ in range(1000):
Y_ = m * X + b
# loss = ((Y - Y_)**2).sum()
loss = loss_fn(Y, Y_)
loss.backward()
# No more manual update!
# with torch.no_grad():
# m -= lr * m.grad
# b -= lr * b.grad
optimizer.step()
# m.grad.zero_()
# b.grad.zero_()
optimizer.zero_grad()
print(m.data.cpu().numpy())
print(b.data.cpu().numpy())
[2.0164788] [1.0602573]
torch.nn.Module
¶torch.nn.Module
es una clase fundamental en la biblioteca PyTorch que proporciona una manera estructurada y flexible de definir todos los aspectos de una red neuronal. Facilita la implementación de una variedad de modelos de aprendizaje profundo, desde los más sencillos hasta arquitecturas altamente complejas.
class ManualLinearRegression(torch.nn.Module):
def __init__(self):
super().__init__()
# To make "a" and "b" real parameters of the model, we need to wrap them with nn.Parameter
self.m = torch.nn.Parameter(torch.randn(1, requires_grad=True, dtype=torch.float))
self.b = torch.nn.Parameter(torch.randn(1, requires_grad=True, dtype=torch.float))
def forward(self, x):
# Computes the outputs / predictions
return self.b + self.m * x
torch.manual_seed(42)
# Now we can create a model and send it at once to the device
model = ManualLinearRegression().to(device)
# We can also inspect its parameters using its state_dict
print(model.state_dict())
lr = 0.01
n_epochs = 1000
loss_fn = torch.nn.MSELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=lr)
# What is this?!?
model.train()
for epoch in range(n_epochs):
# No more manual prediction!
# yhat = a + b * x_tensor
Y_ = model(X)
loss = loss_fn(Y, Y_)
loss.backward()
optimizer.step()
optimizer.zero_grad()
print(model.state_dict())
# Extraemos los parametros del modelo
m = model.state_dict()['m'].item()
b = model.state_dict()['b'].item()
OrderedDict([('m', tensor([0.3367])), ('b', tensor([0.1288]))]) OrderedDict([('m', tensor([2.0161])), ('b', tensor([1.0614]))])
Vamos a visualizar el resultado.
import numpy as np
import matplotlib.pyplot as plt
mu, sigma = 0, 0.5 # media y desviación estándar
noise = np.random.normal(mu, sigma, 10)
X = np.random.rand(10) * 5
Y = 2 * X + 1 + noise
# Crear valores para la línea
x_line = np.linspace(0, 5, 100) # 100 puntos entre 0 y 5
y_line = m * x_line + b # Calcula los valores usando m y b calculados anteriormente
plt.axis([0, 5, 0, 12])
plt.plot(X, Y, 'bo')
# Recta de regresión
plt.title('Recta de regressión')
plt.plot(x_line, y_line, 'r-') # 'r-' crea una línea roja continua
plt.show()